package com.campus.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.counseling.entity.PsychologicalTest;
import com.campus.counseling.entity.TestQuestion;
import com.campus.counseling.entity.TestRecord;
import com.campus.counseling.entity.TestResult;
import com.campus.counseling.model.common.exception.BusinessException;
import com.campus.counseling.model.dto.PsychologicalTestDTO;
import com.campus.counseling.model.mapper.PsychologicalTestMapper;
import com.campus.counseling.model.mapper.TestQuestionMapper;
import com.campus.counseling.model.mapper.TestRecordMapper;
import com.campus.counseling.model.mapper.TestResultMapper;
import com.campus.counseling.model.query.PsychologicalTestQuery;
import com.campus.counseling.model.vo.PsychologicalTestVO;
import com.campus.counseling.model.vo.TestQuestionVO;
import com.campus.counseling.service.PsychologicalTestService;
import com.campus.counseling.util.SecurityUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class PsychologicalTestServiceImpl extends ServiceImpl<PsychologicalTestMapper, PsychologicalTest> implements PsychologicalTestService {
    
    private final TestQuestionMapper testQuestionMapper;
    
    private final TestRecordMapper testRecordMapper;
    
    private final TestResultMapper testResultMapper;
    
    private final ObjectMapper objectMapper;
    
    @Override
    public Page<PsychologicalTestVO> list(PsychologicalTestQuery query) {
        Page<PsychologicalTest> page = new Page<>(query.getPageNum(), query.getPageSize());
        
        LambdaQueryWrapper<PsychologicalTest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(query.getTestType()), PsychologicalTest::getTestType, query.getTestType())
               .eq(query.getStatus() != null, PsychologicalTest::getStatus, query.getStatus())
               .orderByDesc(PsychologicalTest::getCreateTime);
        
        page = page(page, wrapper);
        
        return convertToVOPage(page);
    }
    
    @Override
    public PsychologicalTestVO getTest(Long id) {
        // 根据id获取心理测试
        PsychologicalTest test = getById(id);
        if (test == null) {
            throw new BusinessException("测试不存在");
        }
        return convertToVO(test);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PsychologicalTestDTO dto) {
        PsychologicalTest test = new PsychologicalTest();
        BeanUtils.copyProperties(dto, test);
        test.setScoringMethod(dto.getScoringType());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Long id, PsychologicalTestDTO dto) {
        PsychologicalTest test = getById(id);
        if (test == null) {
            throw new BusinessException("测试不存在");
        }
        BeanUtils.copyProperties(dto, test);
        test.setScoringMethod(dto.getScoringType());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        removeById(id);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long id, Integer status) {
        PsychologicalTest test = getById(id);
        if (test == null) {
            throw new BusinessException("测试不存在");
        }
        test.setStatus(status);
        updateById(test);
    }
    

    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long startTest(Long id) {
        PsychologicalTest test = getById(id);
        if (test == null) {
            throw new BusinessException("测试不存在");
        }
        
        // 创建测试记录
        TestRecord record = new TestRecord();
        record.setTestId(id);
        record.setUserId(SecurityUtils.getUserId());
        record.setStartTime(LocalDateTime.now());
        record.setStatus(0); // 进行中
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        testRecordMapper.insert(record);
        
        // 创建测试结果
        TestResult result = new TestResult();
        result.setRecordId(record.getId());
        result.setTotalScore(0); // 设置初始总分为0
        result.setDimensionScores("{}"); // 设置初始维度得分为空JSON对象
        result.setLevel(""); // 设置初始等级为空字符串
        result.setAnalysis(""); // 设置初始分析为空字符串
        result.setSuggestions(""); // 设置初始建议为空字符串
        result.setReviewedBy(null); // 设置审阅人为null
        result.setReviewTime(null); // 设置审阅时间为null
        result.setReviewComments(""); // 设置审阅意见为空字符串
        result.setCreateTime(LocalDateTime.now());
        result.setUpdateTime(LocalDateTime.now());
        testResultMapper.insert(result);
        
        return record.getId();
    }
    
    @Override
    public List<PsychologicalTestVO> getTestsByType(String type) {
        LambdaQueryWrapper<PsychologicalTest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PsychologicalTest::getTestType, type)
               .eq(PsychologicalTest::getStatus, 1)
               .orderByDesc(PsychologicalTest::getCreateTime);
        
        return list(wrapper).stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<String> getAllTestTypes() {
        LambdaQueryWrapper<PsychologicalTest> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(PsychologicalTest::getTestType)
               .groupBy(PsychologicalTest::getTestType);
        
        return list(wrapper).stream()
                .map(PsychologicalTest::getTestType)
                .filter(type -> type != null && !type.isEmpty())
                .distinct()
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTestType(Long testId, String testType) {
        PsychologicalTest test = getById(testId);
        if (test == null) {
            return false;
        }
        test.setTestType(testType);
        return updateById(test);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateTestType(List<Long> testIds, String testType) {
        return update().set("test_type", testType)
                      .in("id", testIds)
                      .update();
    }
    
    @Override
    public Map<String, Integer> getTestTypeStatistics() {
        return list().stream()
                .filter(test -> test.getTestType() != null)
                .collect(Collectors.groupingBy(
                    PsychologicalTest::getTestType,
                    Collectors.collectingAndThen(Collectors.counting(), Long::intValue)
                ));
    }
    
    @Override
    public List<TestQuestionVO> getQuestions(Long testId) {
        LambdaQueryWrapper<TestQuestion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TestQuestion::getTestId, testId)
               .orderByAsc(TestQuestion::getSortNum);
        
        return testQuestionMapper.selectList(wrapper)
                .stream()
                .map(this::convertQuestionToVO)
                .collect(Collectors.toList());
    }
    
    private TestQuestionVO convertQuestionToVO(TestQuestion question) {
        if (question == null) {
            return null;
        }
        
        TestQuestionVO vo = new TestQuestionVO();
        BeanUtils.copyProperties(question, vo, "options", "optionScores"); // 排除options和optionScores字段的复制
        
        // 处理选项字段
        if (question.getOptions() != null) {
            try {
                // 将JSON字符串转换为List<String>
                List<String> optionsList = objectMapper.readValue(question.getOptions(), new TypeReference<List<String>>() {});
                vo.setOptions(optionsList);
            } catch (Exception e) {
                log.error("处理题目选项失败: {}", question.getOptions(), e);
                vo.setOptions(null);
            }
        }
        
        // 处理选项分值字段
        if (question.getOptionScores() != null) {
            try {
                // 将JSON字符串转换为Map对象
                Map<String, BigDecimal> optionScoresMap = objectMapper.readValue(question.getOptionScores(), new TypeReference<Map<String, BigDecimal>>() {});
                vo.setOptionScores(optionScoresMap);
            } catch (Exception e) {
                log.error("处理选项分值失败: {}", question.getOptionScores(), e);
                vo.setOptionScores(null);
            }
        }
        
        return vo;
    }
    
    private Page<PsychologicalTestVO> convertToVOPage(Page<PsychologicalTest> page) {
        Page<PsychologicalTestVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage, "records");
        
        List<PsychologicalTestVO> voList = page.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        voPage.setRecords(voList);
        return voPage;
    }
    
    @Override
    public PsychologicalTestVO convertToVO(PsychologicalTest test) {
        if (test == null) {
            return null;
        }
        
        PsychologicalTestVO vo = new PsychologicalTestVO();
        BeanUtils.copyProperties(test, vo);
        
        // 将 scoringMethod 映射到 scoringType
        vo.setScoringType(test.getScoringMethod());
        
        // 设置问题列表
        List<TestQuestionVO> questions = getQuestions(test.getId());
        vo.setQuestions(questions);
        
        // 设置统计信息
        vo.setQuestionCount(questions.size());
        
        return vo;
    }
    @Override
    public List<Map<String, Object>> getTestDimensions(Long testId) {
        // 使用 MyBatis-Plus 的 baseMapper 查询维度表
        return baseMapper.getTestDimensions(testId);
    }
} 